home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 June / PCWorld_2007-06_cd.bin / v cisle / tclock / tclocklight-040702-3.exe / source / dll / startmenu.c < prev    next >
C/C++ Source or Header  |  2004-05-19  |  18KB  |  698 lines

  1. /*-------------------------------------------------------------
  2.   startmenu.c : customize start menu
  3.   (C) 1997-2003 Kazuto Sato
  4.   Please read readme.txt about the license.
  5.   
  6.   Written by Kazubon, Nanashi-san
  7. ---------------------------------------------------------------*/
  8.  
  9. #include "tcdll.h"
  10. #include "newapi.h"
  11.  
  12. /* Globals */
  13.  
  14. void InitStartMenu(HWND hwndClock);
  15. void EndStartMenu(void);
  16. void ResetStartMenu(HWND hwndClock);
  17. void ClearStartMenuResource(void);
  18. void CheckStartMenu(void);
  19. BOOL OnDrawItemStartMenu(HWND hwnd, DRAWITEMSTRUCT* pdis);
  20.  
  21. /* Statics */
  22.  
  23. static void InitStartMenuSetting(HWND hwndClock);
  24. static BOOL IsStartMenu(HMENU hmenu);
  25. static void SubclassBaseBar(void);
  26. static void UnSubclassBaseBar(void);
  27. static void SubclassUserPaneXP(void);
  28. static void UnSubclassUserPaneXP(void);
  29. static void TransStartMenu(void);
  30. static void UnTransStartMenu(void);
  31. static LRESULT CALLBACK WndProcBaseBar(HWND hwnd, UINT message,
  32.     WPARAM wParam, LPARAM lParam);
  33. static void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint);
  34. static LRESULT CALLBACK WndProcUserPaneXP(HWND hwnd, UINT message,
  35.     WPARAM wParam, LPARAM lParam);
  36. static void OnPaintUserPaneXP(HWND hwnd, HDC hdc);
  37.  
  38. // Start menu (BaseBar) of IE 4 or later
  39. static HWND m_hwndBaseBar = NULL;           // window handle
  40. static WNDPROC m_oldWndProcBaseBar = NULL;  // window procedure
  41. // Start menu (DV2ControlHost) of Windows XP
  42. static HWND m_hwndDV2ContHost = NULL;       // window handle
  43. static HWND m_hwndUserPaneXP = NULL;        // window handle of top pane
  44. static WNDPROC m_oldWndProcUserPaneXP = NULL; // window procedure of top pane
  45.  
  46. static BOOL m_bStartMenu = FALSE;  // customize start menu
  47. static BOOL m_bSubclass = FALSE;   // subclassify
  48. static HDC m_hdcMemMenu = NULL;    // offscreen DC
  49. static HBITMAP m_hbmpMenu = NULL;  // offscreen BMP
  50. static COLORREF m_colMenu;         // color
  51. static BOOL m_bTile = FALSE;       // tile
  52. static int m_alpha = 255;          // transparency
  53. static char *m_section = "StartMenu";
  54.  
  55. /*--------------------------------------------------
  56.   initialize
  57. ----------------------------------------------------*/
  58. void InitStartMenu(HWND hwndClock)
  59. {
  60.     InitStartMenuSetting(hwndClock);
  61.     
  62.     // XP
  63.     if(g_winver&WINXP) SubclassUserPaneXP();
  64.     
  65.     // IE 4 or later
  66.     if(g_bIE4) SubclassBaseBar();
  67.     
  68.     if((g_winver&WIN2000) && m_hwndBaseBar)
  69.         TransStartMenu();
  70. }
  71.  
  72. /*--------------------------------------------------
  73.   clear up
  74. ----------------------------------------------------*/
  75. void EndStartMenu(void)
  76. {
  77.     if(g_bIE4) UnSubclassBaseBar();
  78.     
  79.     if(g_winver&WINXP) UnSubclassUserPaneXP();
  80.     
  81.     if((g_winver&WIN2000) && m_alpha < 255) UnTransStartMenu();
  82.     
  83.     ClearStartMenuResource();
  84. }
  85.  
  86. /*--------------------------------------------------
  87.   refresh settings
  88. ----------------------------------------------------*/
  89. void ResetStartMenu(HWND hwndClock)
  90. {
  91.     BOOL bOld = m_bSubclass;
  92.     int oldalpha = m_alpha;
  93.     
  94.     ClearStartMenuResource();
  95.     InitStartMenuSetting(hwndClock);
  96.     
  97.     if(!bOld && m_bSubclass)
  98.     {
  99.         if(g_bIE4)  SubclassBaseBar();
  100.         if(g_winver&WINXP) SubclassUserPaneXP();
  101.     }
  102.     else if(bOld && !m_bSubclass)
  103.     {
  104.         if(g_winver&WINXP) UnSubclassUserPaneXP();
  105.         if(g_bIE4) UnSubclassBaseBar();
  106.     }
  107.     
  108.     if(g_winver&WIN2000)
  109.     {
  110.         if(m_alpha < 255)
  111.         {
  112.             if(m_hwndBaseBar)
  113.                 TransStartMenu();
  114.             else if(m_hwndDV2ContHost)
  115.             {
  116.                 if((GetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE)
  117.                     & WS_EX_LAYERED))
  118.                         TransStartMenu();
  119.             }
  120.         }
  121.         else if(oldalpha < 255 && m_alpha == 255)
  122.             UnTransStartMenu();
  123.     }
  124. }
  125.  
  126. /*--------------------------------------------------
  127.   clear up resources
  128. ----------------------------------------------------*/
  129. void ClearStartMenuResource(void)
  130. {
  131.     if(m_hdcMemMenu) DeleteDC(m_hdcMemMenu);
  132.     m_hdcMemMenu = NULL;
  133.     if(m_hbmpMenu) DeleteObject(m_hbmpMenu);
  134.     m_hbmpMenu = NULL;
  135. }
  136.  
  137. /*--------------------------------------------------
  138.   check if start menu is destroyed
  139.   called in OnTimerMain of wndproc.c
  140. ----------------------------------------------------*/
  141. void CheckStartMenu(void)
  142. {
  143.     if(m_hwndBaseBar && !IsWindow(m_hwndBaseBar))
  144.     {
  145.         SubclassBaseBar();
  146.         if((g_winver&WIN2000) && m_hwndBaseBar)
  147.             TransStartMenu();
  148.     }
  149.     
  150.     if(m_hwndDV2ContHost && !IsWindow(m_hwndDV2ContHost))
  151.     {
  152.         SubclassUserPaneXP();
  153.     }
  154. }
  155.  
  156. /*------------------------------------------------
  157.   owner-drawn start menu (Win95 without IE 4)
  158.   called in taskbar.c
  159. --------------------------------------------------*/
  160. BOOL OnDrawItemStartMenu(HWND hwnd, DRAWITEMSTRUCT* pdis)
  161. {
  162.     HDC hdc, hdcMem;
  163.     HBITMAP hbmpMem;
  164.     RECT rcBox, rcItem;
  165.     HBRUSH hbr;
  166.     
  167.     if(!m_bStartMenu) return FALSE;
  168.     if(!IsStartMenu((HMENU)pdis->hwndItem)) return FALSE;
  169.     
  170.     hdc = pdis->hDC;
  171.     CopyRect(&rcItem, &(pdis->rcItem));
  172.     GetClipBox(hdc, &rcBox); // menu size
  173.     
  174.     // offscreen DC and BMP
  175.     hdcMem = CreateCompatibleDC(hdc);
  176.     hbmpMem = CreateCompatibleBitmap(hdc, rcBox.right, rcBox.bottom);
  177.     SelectObject(hdcMem, hbmpMem);
  178.     hbr = CreateSolidBrush(GetSysColor(COLOR_MENU));
  179.     FillRect(hdcMem, &rcBox, hbr);
  180.     
  181.     SelectObject(hdcMem, (HFONT)GetCurrentObject(hdc, OBJ_FONT));
  182.     
  183.     // background and text color
  184.     if(pdis->itemState & ODS_FOCUS)
  185.     {
  186.         SetTextColor(hdcMem, GetSysColor(COLOR_HIGHLIGHTTEXT));
  187.         SetBkColor(hdcMem, GetSysColor(COLOR_HIGHLIGHT));
  188.     }
  189.     else
  190.     {
  191.         SetTextColor(hdcMem, GetSysColor(COLOR_MENUTEXT));
  192.         SetBkColor(hdcMem, GetSysColor(COLOR_MENU));
  193.     }
  194.     
  195.     // default drawing
  196.     pdis->hDC = hdcMem;
  197.     CallOldTaskbarWndProc(hwnd, WM_DRAWITEM, 0, (LPARAM)pdis);
  198.     
  199.     // width of "Windows95"
  200.     rcItem.right = pdis->rcItem.left;
  201.     
  202.     if(rcItem.right > 0)
  203.     {
  204.         COLORREF col;
  205.         
  206.         if(!m_bTile)
  207.         {
  208.             col = m_colMenu;
  209.             if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  210.             hbr = CreateSolidBrush(col);
  211.             FillRect(hdcMem, &rcItem, hbr);
  212.             DeleteObject(hbr);
  213.         }
  214.         
  215.         if(m_hdcMemMenu && m_hbmpMenu)
  216.         {
  217.             int i, j;
  218.             int wbmp, hbmp;
  219.             
  220.             GetBmpSize(m_hbmpMenu, &wbmp, &hbmp);
  221.             
  222.             for(i = 0; ; i++)
  223.             {
  224.                 int y, ysrc, h, x, w;
  225.                 for(j = 0; ; j++)
  226.                 {
  227.                     y = rcBox.bottom - ((i + 1) * hbmp);
  228.                     ysrc = 0;
  229.                     h = hbmp;
  230.                     if(y < 0)
  231.                     {
  232.                         y = 0;
  233.                         ysrc = ((i + 1) * hbmp) - rcBox.bottom;
  234.                         h -= ysrc;
  235.                     }
  236.                     x = j * wbmp; w = wbmp;
  237.                     if(x + w > rcItem.right)
  238.                     {
  239.                         w -= ((j + 1) * wbmp) - rcItem.right;
  240.                     }
  241.                     if(w > 0 && h > 0)
  242.                         BitBlt(hdcMem, x, y, w, h,
  243.                             m_hdcMemMenu, 0, ysrc, SRCCOPY);
  244.                     if(!m_bTile || w < wbmp) break;
  245.                 }
  246.                 if(!m_bTile || y == 0) break;
  247.             }
  248.         }
  249.     }
  250.     
  251.     BitBlt(hdc, 0, rcItem.top,
  252.         pdis->rcItem.right, rcItem.bottom - rcItem.top,
  253.         hdcMem, 0, rcItem.top, SRCCOPY);
  254.     pdis->hDC = hdc;
  255.     
  256.     DeleteDC(hdcMem);
  257.     DeleteObject(hbmpMem);
  258.     
  259.     return TRUE;
  260. }
  261.  
  262. /*--------------------------------------------------
  263.   read settings
  264. ----------------------------------------------------*/
  265. void InitStartMenuSetting(HWND hwndClock)
  266. {
  267.     char fname[MAX_PATH], s[MAX_PATH];
  268.     
  269.     m_bStartMenu = GetMyRegLong(NULL, "StartMenu", FALSE);
  270.     m_bStartMenu = GetMyRegLong(m_section, "StartMenu", m_bStartMenu);
  271.     
  272.     if(g_winver&WIN2000)
  273.     {
  274.         m_alpha = GetMyRegLong(NULL, "AlphaStartMenu", 0);
  275.         m_alpha = GetMyRegLong(m_section, "Alpha", m_alpha);
  276.         m_alpha = 255 - (m_alpha * 255 / 100);
  277.         if(m_alpha < 8) m_alpha = 8;
  278.         else if(m_alpha > 255) m_alpha = 255;
  279.     }
  280.     
  281.     if(m_bStartMenu || m_alpha < 255) m_bSubclass = TRUE;
  282.     
  283.     if(!m_bStartMenu) return;
  284.     
  285.     m_colMenu = GetMyRegLong(NULL, "StartMenuCol",
  286.         RGB(128, 128, 128));
  287.     m_colMenu = GetMyRegLong(m_section, "Color", m_colMenu);
  288.     
  289.     m_bTile = GetMyRegLong(NULL, "StartMenuTile", FALSE);
  290.     m_bTile = GetMyRegLong(m_section, "Tile", m_bTile);
  291.     
  292.     GetMyRegStr(NULL, "StartMenuBmp", s, MAX_PATH, "");
  293.     GetMyRegStr(m_section, "Bitmap", fname, MAX_PATH, s);
  294.     
  295.     if(fname[0]) // load bitmap
  296.     {
  297.         char fname2[MAX_PATH];
  298.         RelToAbs(fname2, fname);
  299.         m_hbmpMenu = ReadBitmap(hwndClock, fname2, FALSE);
  300.         if(m_hbmpMenu)
  301.         {
  302.             HDC hdc;
  303.             hdc = GetDC(hwndClock);
  304.             m_hdcMemMenu = CreateCompatibleDC(hdc);
  305.             SelectObject(m_hdcMemMenu, m_hbmpMenu);
  306.             ReleaseDC(hwndClock, hdc);
  307.         }
  308.     }
  309. }
  310.  
  311. /*--------------------------------------------------
  312.   HMENU is start menu ?
  313. ----------------------------------------------------*/
  314. BOOL IsStartMenu(HMENU hmenu)
  315. {
  316.     int i, count, id;
  317.     
  318.     count = GetMenuItemCount(hmenu);
  319.     for(i = 0; i < count; i++)
  320.     {
  321.         id = GetMenuItemID(hmenu, i);
  322.         // "Help" item
  323.         if(id == 503) return TRUE;
  324.     }
  325.     return FALSE;
  326. }
  327.  
  328. /*--------------------------------------------------
  329.   subclassify "BaseBar" (Start Menu of IE 4 or later)
  330. ----------------------------------------------------*/
  331. void SubclassBaseBar(void)
  332. {
  333.     HWND hwnd, hwndChild;
  334.     HWND hwndFound;
  335.     char classname[80];
  336.     
  337.     m_hwndBaseBar = NULL;
  338.     
  339.     if(m_hwndDV2ContHost) return;
  340.     
  341.     if(!m_bSubclass) return;
  342.     
  343.     // search
  344.     hwnd = GetDesktopWindow();
  345.     hwnd = GetWindow(hwnd, GW_CHILD);
  346.     hwndFound = NULL;
  347.     while(hwnd)
  348.     {
  349.         GetClassName(hwnd, classname, 80);
  350.         if(strcmp(classname, "BaseBar") == 0)
  351.         {
  352.             if(GetWindowThreadProcessId(hwnd, NULL) ==
  353.                 GetCurrentThreadId())
  354.             {
  355.                 POINT ptParent = { 0, 0 };
  356.                 RECT rcWinChild;
  357.                 
  358.                 hwndChild = GetWindow(hwnd, GW_CHILD);
  359.                 ClientToScreen(hwnd, &ptParent);
  360.                 GetWindowRect(hwndChild, &rcWinChild);
  361.                 if(rcWinChild.left - ptParent.x == 21)
  362.                 {
  363.                     hwndFound = hwnd; break;
  364.                 }
  365.                 else if(rcWinChild.right - rcWinChild.left == 0)
  366.                 {
  367.                     if(hwndFound == NULL || (int)hwndFound > (int)hwnd)
  368.                         hwndFound = hwnd;
  369.                 }
  370.             }
  371.         }
  372.         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  373.     }
  374.     m_hwndBaseBar = hwndFound;
  375.     
  376.     /*{
  377.         char s[80];
  378.         wsprintf(s, "%X", m_hwndBaseBar);
  379.         WriteDebug(s);
  380.     }*/
  381.     
  382.     if(m_hwndBaseBar == NULL) return;
  383.     
  384.     // if(IsSubclassed(m_hwndBaseBar)) return;
  385.     
  386.     m_oldWndProcBaseBar = (WNDPROC)GetWindowLong(m_hwndBaseBar, GWL_WNDPROC);
  387.     SetWindowLong(m_hwndBaseBar, GWL_WNDPROC, (LONG)WndProcBaseBar);
  388. }
  389.  
  390. /*--------------------------------------------------
  391.   restore window procedure of "BaseBar"
  392. ----------------------------------------------------*/
  393. void UnSubclassBaseBar(void)
  394. {
  395.     if(m_hwndBaseBar && IsWindow(m_hwndBaseBar))
  396.     {
  397.         if(m_oldWndProcBaseBar)
  398.             SetWindowLong(m_hwndBaseBar, GWL_WNDPROC,
  399.                 (LONG)m_oldWndProcBaseBar);
  400.     }
  401.     m_oldWndProcBaseBar = NULL;
  402. }
  403.  
  404. /*--------------------------------------------------
  405.   Subclassify "Desktop User Pane" window of XP Start Menu
  406. ----------------------------------------------------*/
  407. void SubclassUserPaneXP(void)
  408. {
  409.     if(!m_bSubclass) return;
  410.     
  411.     m_hwndDV2ContHost = FindWindow("DV2ControlHost", NULL);
  412.     if(!m_hwndDV2ContHost) return;
  413.     m_hwndUserPaneXP = FindWindowEx(m_hwndDV2ContHost, NULL,
  414.         "Desktop User Pane", NULL);
  415.     if(!m_hwndUserPaneXP) return;
  416.     
  417.     if(IsSubclassed(m_hwndUserPaneXP)) return;
  418.     
  419.     m_oldWndProcUserPaneXP = (WNDPROC)GetWindowLong(m_hwndUserPaneXP,
  420.         GWL_WNDPROC);
  421.     SetWindowLong(m_hwndUserPaneXP, GWL_WNDPROC, (LONG)WndProcUserPaneXP);
  422. }
  423.  
  424. /*--------------------------------------------------
  425.   restore window procedure of "Desktop User Pane"
  426. ----------------------------------------------------*/
  427. void UnSubclassUserPaneXP(void)
  428. {
  429.     if(m_hwndUserPaneXP && IsWindow(m_hwndUserPaneXP))
  430.     {
  431.         if(m_oldWndProcUserPaneXP)
  432.         {
  433.             SetWindowLong(m_hwndUserPaneXP, GWL_WNDPROC,
  434.                 (LONG)m_oldWndProcUserPaneXP);
  435.             SendMessage(GetParent(m_hwndUserPaneXP), WM_SYSCOLORCHANGE, 0, 0);
  436.         }
  437.     }
  438.     m_oldWndProcUserPaneXP = NULL;
  439. }
  440.  
  441. /*--------------------------------------------------
  442.   set transparency of Start menu
  443. ----------------------------------------------------*/
  444. void TransStartMenu(void)
  445. {
  446.     LONG style;
  447.     
  448.     if(m_alpha >= 255) return;
  449.     
  450.     if(m_hwndDV2ContHost)
  451.     {
  452.         if(m_hwndUserPaneXP)
  453.             InvalidateRect(m_hwndUserPaneXP, NULL, TRUE);
  454.         style = GetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE);
  455.         SetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE, style|WS_EX_LAYERED);
  456.         MySetLayeredWindowAttributes(m_hwndDV2ContHost,
  457.             0, (BYTE)m_alpha, LWA_ALPHA);
  458.         //InvalidateRect(m_hwndDV2ContHost, NULL, TRUE);
  459.     }
  460.     if(m_hwndBaseBar)
  461.     {
  462.         style = GetWindowLong(m_hwndBaseBar, GWL_EXSTYLE);
  463.         SetWindowLong(m_hwndBaseBar, GWL_EXSTYLE, style|WS_EX_LAYERED);
  464.         MySetLayeredWindowAttributes(m_hwndBaseBar,
  465.             0, (BYTE)m_alpha, LWA_ALPHA);
  466.     }
  467. }
  468.  
  469. /*--------------------------------------------------
  470.   restore transparency of Start menu
  471. ----------------------------------------------------*/
  472. void UnTransStartMenu(void)
  473. {
  474.     LONG style;
  475.     
  476.     if(m_hwndDV2ContHost)
  477.     {
  478.         style = GetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE);
  479.         style &= ~WS_EX_LAYERED;
  480.         SetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE, style);
  481.         MySetLayeredWindowAttributes(m_hwndDV2ContHost,
  482.             GetSysColor(COLOR_3DFACE), 0, LWA_COLORKEY);
  483.         InvalidateRect(m_hwndDV2ContHost, NULL, TRUE);
  484.     }
  485.     if(m_hwndBaseBar)
  486.     {
  487.         style = GetWindowLong(m_hwndBaseBar, GWL_EXSTYLE);
  488.         style &= ~WS_EX_LAYERED;
  489.         SetWindowLong(m_hwndBaseBar, GWL_EXSTYLE, style);
  490.         MySetLayeredWindowAttributes(m_hwndBaseBar,
  491.             GetSysColor(COLOR_3DFACE), 0, LWA_COLORKEY);
  492.     }
  493. }
  494.  
  495. /*------------------------------------------------
  496.   window procedure of Start Menu (BaseBar)
  497.   of IE 4 or later
  498. --------------------------------------------------*/
  499. LRESULT CALLBACK WndProcBaseBar(HWND hwnd, UINT message,
  500.     WPARAM wParam, LPARAM lParam)
  501. {
  502.     switch(message)
  503.     {
  504.         case WM_PAINT:
  505.         {
  506.             PAINTSTRUCT ps;
  507.             HDC hdc;
  508.             if(!m_bStartMenu) break;
  509.             hdc = BeginPaint(hwnd, &ps);
  510.             OnPaintStartmenuIE4(hwnd, hdc, FALSE);
  511.             EndPaint(hwnd, &ps);
  512.             return 0;
  513.         }
  514.         case WM_PRINT:
  515.         {
  516.             LRESULT r;
  517.             if(!m_bStartMenu) break;
  518.             r = CallWindowProc(m_oldWndProcBaseBar,
  519.                 hwnd, message, wParam, lParam);
  520.             OnPaintStartmenuIE4(hwnd, (HDC)wParam, TRUE);
  521.             return r;
  522.         }
  523.         case WM_STYLECHANGED:
  524.         {
  525.             STYLESTRUCT* pss = (STYLESTRUCT*)lParam;
  526.             if(m_alpha < 255 && wParam == GWL_EXSTYLE &&
  527.                 !(pss->styleNew & WS_EX_LAYERED))
  528.             {
  529.                 TransStartMenu();
  530.                 return 0;
  531.             }
  532.             break;
  533.         }
  534.     }
  535.     return CallWindowProc(m_oldWndProcBaseBar, hwnd, message, wParam, lParam);
  536. }
  537.  
  538. /*------------------------------------------------
  539.   paint StartMenu (BaseBar) of IE 4 or later
  540. --------------------------------------------------*/
  541. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint)
  542. {
  543.     RECT rc, rcWin, rcChild;
  544.     POINT pt;
  545.     COLORREF col;
  546.     HBRUSH hbr;
  547.     BITMAP bmp;
  548.     int hClient, wClient;
  549.     
  550.     GetWindowRect(GetWindow(hwnd, GW_CHILD), &rcChild);
  551.     GetWindowRect(hwnd, &rcWin);
  552.     GetClientRect(hwnd, &rc);
  553.     pt.x = 0; pt.y = 0;
  554.     ClientToScreen(hwnd, &pt);
  555.     if(pt.x == rcChild.left) return;
  556.     
  557.     rc.right = 21;
  558.     wClient = rc.right; hClient = rc.bottom;
  559.     if(bPrint)
  560.     {
  561.         int dx, dy;
  562.         dx = pt.x - rcWin.left; dy = pt.y - rcWin.top;
  563.         rc.left += dx; rc.right += dx;
  564.         rc.top += dy; rc.bottom += dy;
  565.     }
  566.     
  567.     // fill with color
  568.     col = m_colMenu;
  569.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  570.     hbr = CreateSolidBrush(col);
  571.     FillRect(hdc, &rc, hbr);
  572.     DeleteObject(hbr);
  573.     
  574.     // draw bitmap
  575.     if(m_hbmpMenu)
  576.     {
  577.         int i, j;
  578.         GetObject(m_hbmpMenu, sizeof(BITMAP), &bmp);
  579.         
  580.         for(i = 0; ; i++)
  581.         {
  582.             int y, ysrc, h, x, w;
  583.             for(j = 0; ; j++)
  584.             {
  585.                 y = hClient - ((i + 1) * bmp.bmHeight);
  586.                 ysrc = 0;
  587.                 h = bmp.bmHeight;
  588.                 if(y < 0)
  589.                 {
  590.                     y = 0;
  591.                     ysrc = ((i + 1) * bmp.bmHeight) - hClient;
  592.                     h -= ysrc;
  593.                 }
  594.                 x = j * bmp.bmWidth; w = bmp.bmWidth;
  595.                 if(x + w > wClient)
  596.                 {
  597.                     w -= ((j + 1) * bmp.bmWidth) - wClient;
  598.                 }
  599.                 if(w > 0 && h > 0)
  600.                     BitBlt(hdc, rc.left + x, rc.top + y, w, h,
  601.                         m_hdcMemMenu, 0, ysrc, SRCCOPY);
  602.                 if(!m_bTile || w < bmp.bmWidth) break;
  603.             }
  604.             if(!m_bTile || y == 0) break;
  605.         }
  606.     }
  607. }
  608.  
  609. /*------------------------------------------------
  610.   window procedure of
  611.   top child window of XP Start Menu
  612. --------------------------------------------------*/
  613. LRESULT CALLBACK WndProcUserPaneXP(HWND hwnd, UINT message,
  614.     WPARAM wParam, LPARAM lParam)
  615. {
  616.     switch(message)
  617.     {
  618.         case WM_NOTIFY:
  619.             if(m_alpha < 255)
  620.             {
  621.                 LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
  622.                 if(!(style&WS_EX_LAYERED))
  623.                     PostMessage(hwnd, WM_USER+1, 0, 0);
  624.             }
  625.             
  626.             if(m_bStartMenu)
  627.             {
  628.                 HDC hdc = GetDC(hwnd);
  629.                 OnPaintUserPaneXP(hwnd, hdc);
  630.                 ReleaseDC(hwnd, hdc);
  631.                 return 0;
  632.             }
  633.             break;
  634.         case (WM_USER+1):
  635.             if(m_alpha < 255)
  636.                 TransStartMenu();
  637.             return 0;
  638.         case WM_PAINT:
  639.         {
  640.             PAINTSTRUCT ps;
  641.             HDC hdc;
  642.             if(!m_bStartMenu) break;
  643.             hdc = BeginPaint(hwnd, &ps);
  644.             OnPaintUserPaneXP(hwnd, hdc);
  645.             EndPaint(hwnd, &ps);
  646.             return 0;
  647.         }
  648.         case WM_CTLCOLORSTATIC:
  649.             if(m_bStartMenu) return 0;
  650.             break;
  651.         case WM_DRAWITEM:
  652.             if(m_bStartMenu) return 0;
  653.             break;
  654.     }
  655.     return CallWindowProc(m_oldWndProcUserPaneXP,
  656.         hwnd, message, wParam, lParam);
  657. }
  658.  
  659. /*----------------------------------------------------
  660.   paint "Desktop User Pane" window of XP Start Menu
  661. -----------------------------------------------------*/
  662. void OnPaintUserPaneXP(HWND hwnd, HDC hdc)
  663. {
  664.     RECT rc;
  665.     COLORREF col;
  666.     HBRUSH hbr;
  667.     int wClient, hClient;
  668.     
  669.     GetClientRect(hwnd, &rc);
  670.     
  671.     wClient = rc.right; hClient = rc.bottom;
  672.     
  673.     col = m_colMenu;
  674.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  675.     hbr = CreateSolidBrush(col);
  676.     FillRect(hdc, &rc, hbr);
  677.     DeleteObject(hbr);
  678.     
  679.     if(m_hbmpMenu)
  680.     {
  681.         int x, y;
  682.         int wbmp, hbmp;
  683.         
  684.         GetBmpSize(m_hbmpMenu, &wbmp, &hbmp);
  685.         
  686.         for(y = 0; y < hClient; y += hbmp)
  687.         {
  688.             for(x = 0; x < wClient; x += wbmp)
  689.             {
  690.                 BitBlt(hdc, x, y, wbmp, hbmp, m_hdcMemMenu, 0, 0, SRCCOPY);
  691.                 if(!m_bTile) break;
  692.             }
  693.             if(!m_bTile) break;
  694.         }
  695.     }
  696. }
  697.  
  698.